/**
 * @author haina.z@163.com
 * @brief bsp usart
 * @version V1.0
 */

/** Includes -----------------------------------------------------------------*/
#include "public_defs.h"
#include "prj_config.h"
#include "apm32f10x_rcm.h"
#include "apm32f10x_usart.h"
#include "apm32f10x_misc.h"
#include "bsp_usart.h"

/** Macros and constants -----------------------------------------------------*/
#define RS485_COM                           USART2
#define RS485_COM_CLK                       RCM_APB1_PERIPH_USART2
#define RS485_COM_IRQn                      USART2_IRQn
#define RS485_COM_IRQHandler                USART2_IRQHandler

#define RS485_COM_TX_PIN                    GPIO_PIN_2
#define RS485_COM_TX_GPIO_PORT              GPIOA
#define RS485_COM_TX_GPIO_CLK               RCM_APB2_PERIPH_GPIOA

#define RS485_COM_RX_PIN                    GPIO_PIN_3
#define RS485_COM_RX_GPIO_PORT              GPIOA
#define RS485_COM_RX_GPIO_CLK               RCM_APB2_PERIPH_GPIOA

#define DEBUG_USART                         RS485_COM

/** Type definitions ---------------------------------------------------------*/

/** Private variable definitions (static) ------------------------------------*/

/** Function declarations (prototypes) ---------------------------------------*/

/** Public variable definitions ----------------------------------------------*/

/** Pre-compile check --------------------------------------------------------*/

/** Code ---------------------------------------------------------------------*/

/**
 * Use USART2 in modbus
 */

/**
 * @brief Uart2, PA2/TX2, PA3/RX2
 * RS485通讯，PA4为R/T口
 */
void Bsp_Usart_Init(void)
{
    GPIO_Config_T GPIO_configStruct;
    USART_Config_T USART_ConfigStruct;

    /* Enable GPIO clock */
    RCM_EnableAPB2PeriphClock(RS485_COM_TX_GPIO_CLK | RS485_COM_RX_GPIO_CLK | RS485_COM_RT_GPIO_CLK);
    /* Enable USART clock */
    RCM_EnableAPB1PeriphClock(RS485_COM_CLK);

    /* Configure USART Tx as alternate function push-pull */
    GPIO_configStruct.mode = GPIO_MODE_AF_PP;
    GPIO_configStruct.pin = RS485_COM_TX_PIN;
    GPIO_configStruct.speed = GPIO_SPEED_50MHz;
    GPIO_Config(RS485_COM_TX_GPIO_PORT, &GPIO_configStruct);

    /* Configure USART Rx as input floating */
    GPIO_configStruct.mode = GPIO_MODE_IN_FLOATING;
    GPIO_configStruct.pin = RS485_COM_RX_PIN;
    GPIO_Config(RS485_COM_RX_GPIO_PORT, &GPIO_configStruct);

    /* Configure USART RT as General purpose output push-pull */
    GPIO_configStruct.mode = GPIO_MODE_OUT_PP;
    GPIO_configStruct.pin = RS485_COM_RT_PIN;
    GPIO_configStruct.speed = GPIO_SPEED_50MHz;
    GPIO_Config(RS485_COM_RT_GPIO_PORT, &GPIO_configStruct);
    mSetRS485Recv();

    /* USART configuration */
    USART_ConfigStruct.baudRate = BSP_USART_BAUDRATE;
    USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;
    USART_ConfigStruct.mode = USART_MODE_TX_RX;
    USART_ConfigStruct.parity = USART_PARITY_NONE;
    USART_ConfigStruct.stopBits = USART_STOP_BIT_1;
    USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;
    USART_Config(RS485_COM, &USART_ConfigStruct);

    /* Enable USART */
    USART_Enable(RS485_COM);

    // Disable rx&tx interrupt
    // USART_EnableInterrupt(RS485_COM, USART_INT_TXC);
    // USART_EnableInterrupt(RS485_COM, USART_INT_RXBNE);
    // NVIC_EnableIRQRequest(RS485_COM_IRQn, 1, 0);
}

void Bsp_Usart_Deinit(void)
{
    GPIO_Config_T GPIO_configStruct;

    NVIC_DisableIRQRequest(RS485_COM_IRQn);
    USART_DisableInterrupt(RS485_COM, USART_INT_RXBNE);
    USART_DisableInterrupt(RS485_COM, USART_INT_TXC);

    USART_Disable(RS485_COM);

    GPIO_ConfigStructInit(&GPIO_configStruct);
    GPIO_configStruct.pin = RS485_COM_TX_PIN;
    GPIO_Config(RS485_COM_TX_GPIO_PORT, &GPIO_configStruct);
    GPIO_configStruct.pin = RS485_COM_RX_PIN;
    GPIO_Config(RS485_COM_RX_GPIO_PORT, &GPIO_configStruct);
    GPIO_configStruct.pin = RS485_COM_RT_PIN;
    GPIO_Config(RS485_COM_RT_GPIO_PORT, &GPIO_configStruct);

    RCM_DisableAPB2PeriphClock(RS485_COM_TX_GPIO_CLK | RS485_COM_RX_GPIO_CLK | RS485_COM_RT_GPIO_CLK);
    RCM_DisableAPB1PeriphClock(RS485_COM_CLK);
}

#if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
int fputc(int ch, FILE *f)
{
    mSetRS485Send();

    /* send a byte of data to the serial port */
    USART_TxData(DEBUG_USART, (uint8_t)ch);

    /* wait for the data to be send  */
    while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);

    return (ch);
}
#endif

/******************************** End of file *********************************/
